from __future__ import division
import itertools as it

from . import *

class ListWrapper(object):
	"""Wrapper class for fast double linked list. 
	List data is represented by float numbers.

	Assure to load compiled lib correctly.
	"""
	def __init__(self):
		get_list_iterator = listlib.getListIterator
		get_list_iterator.restype = c.POINTER(Iterator)

		self._itr = get_list_iterator()
		self._citr = self._itr.contents
		#print dir(self._itr)

	def __len__(self):
		clist = self._citr.list.contents
		#print dir(clist)
		return getattr(clist, 'size')

	def __iter__(self):
		self._i = 0
		self._array = list(self.toarray())
		return self

	def next(self):
		
		if self._i > len(self)-1: 
			self._i = 0
			raise StopIteration 
		else: 
			r = self._array[self._i]
			self._i += 1
			return r

		#for i in self.toarray(): i

	def update(self, iterable):
		"""Append iterable iterable at the end of the list.
		"""
		for item in iterable:
			self.addelement(item)

	def addelement(self, number):
		"""Add single float number in tail of list. 
		number could be everything that support cast to float.
		"""
		try:
			number = float(number)
		except:
			raise TypeError
		data = c.c_float(number)
		add_element = listlib.addElement
		add_element.retype = None
		r = add_element(self._itr, data)

	def toarray(self):
		"""Return native-python list with all linked-list elements.
		"""
		Floatarray = c.c_float*len(self)
		to_array = listlib.toArray
		to_array.restype = c.POINTER(Floatarray)
		res = to_array(self._itr).contents
		#print dir(res)
	
		return list(res)

	@property
	def average(self):
		"""Mean (average) of dataset.
		"""
		av = listlib.average
		av.restype = c.c_float
		res = av(self._itr)

		return res

	@property
	def deviation(self):
		"""Standard deviation of dataset.
		"""
		d = listlib.deviation
		d.restype = c.c_float
		res = d(self._itr)

		return res

####################################################################### decorators and utilitys

def lists2ListWrapper(f):
	"""Decorator for a function that should return a list of list [[]].
	When decorated it will return a ListWrapper contains all sublists.
	"""
	def newf(*a, **k):
		lists = f(*a, **k)
		l = ListWrapper()
		l.update(it.chain(*lists))
		return l
	return newf


